/**
 * File: CreateGraphStatisticFile.java
 * Created by: mhaimel
 * Created on: May 21, 2010
 * CVS:  $Id: CreateGraphStatisticFile.java 1.0 May 21, 2010 2:52:25 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.controller.graph;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import uk.ac.ebi.curtain.controller.SingleSubmitController;
import uk.ac.ebi.curtain.model.graph.Arc;
import uk.ac.ebi.curtain.model.graph.Node;
import uk.ac.ebi.curtain.model.graph.NodeEdge;
import uk.ac.ebi.curtain.model.graph.GraphAccess.TouchEach;
import uk.ac.ebi.curtain.model.graph.curtain.CategoryReadInfo;
import uk.ac.ebi.curtain.model.graph.curtain.ContigInfo;
import uk.ac.ebi.curtain.model.graph.curtain.CurtainGraph;
import uk.ac.ebi.curtain.model.graph.curtain.ReadWrapper;
import uk.ac.ebi.curtain.utils.CurtainUncheckedException;
import uk.ac.ebi.curtain.utils.io.impl.FileIO;

/**
 * @author mhaimel
 *
 */
public class CreateGraphStatisticFile extends SingleSubmitController<Serializable, Serializable> {

	private static final String SEP = "\t";

	@Override
	protected void singleSubmit(List<Serializable> inputList) {
		CurtainGraph graph = getContext().getGraph();
		String statsFilePrefix = getStatsFilePrefix();
		File nodeFile = getContext().currentFiles().getGraphStatistic(statsFilePrefix+"_node");
		File arcFile = getContext().currentFiles().getGraphStatistic(statsFilePrefix+"_arc");
		getLog().info("Store Node statistics to file " + nodeFile + "...");
		PrintWriter out = null;
		try {
			out = new FileIO(nodeFile,false).getPrintWriter();
			printNodeStats(out,graph);
		} catch (IOException e) {
			throw new CurtainUncheckedException("Problems writing node statistics to " + nodeFile,e);
		} finally{
			FileIO.closeQuietly(out);
		}
		getLog().info("Store Arc statistics to file " + arcFile + "...");
		out = null;
		try {
			out = new FileIO(arcFile,false).getPrintWriter();
			printArcStats(out,graph);
		} catch (IOException e) {
			throw new CurtainUncheckedException("Problems writing arc statistics to " + nodeFile,e);
		} finally{
			FileIO.closeQuietly(out);
		}
		getLog().info("Finished storing Graph Statistics!");
		for(Serializable s : inputList){
			submit(s);
		}
	}

	private void printNodeStats(PrintWriter out, CurtainGraph cGraph) {
		final AtomicInteger cat = new AtomicInteger(cGraph.getCategories());
		out.print("nodeId");
		out.print(SEP);
		for(int i = 0; i < cat.get(); ++i){
			out.print("cov"+i);
			out.print(SEP);
			out.print("pLeft"+i);
			out.print(SEP);
			out.print("pRight"+i);
			out.print(SEP);
		}
		out.println();
		final AtomicReference<PrintWriter> pw = new AtomicReference<PrintWriter>(out);
		cGraph.getGraph().processNodes(new TouchEach<Node<ContigInfo, ReadWrapper>>() {

			@Override
			public void touch(Node<ContigInfo, ReadWrapper> node) {
				StringBuffer sb = new StringBuffer();
				sb.append(node.getId().toString())
					.append(SEP);
				for(int i = 0; i < cat.get(); ++i	){
					ContigInfo info = node.getValue();
					Integer sCnt = info.getCoverageSequCount(i);
					if(sCnt > 0){
						Long bpCov = info.getCoverageBpCount(i);
						sb.append((bpCov / sCnt));
					} else {
						sb.append("0");
					}
					sb.append(SEP);
					sb.append(info.getPartial(i, NodeEdge.Start).toString());
					sb.append(SEP);
					sb.append(info.getPartial(i, NodeEdge.End).toString());
					sb.append(SEP);
				}
				pw.get().println(sb.toString());
			}
		});	
	}

	private void printArcStats(PrintWriter out, CurtainGraph cGraph) {
		final AtomicInteger cat = new AtomicInteger(cGraph.getCategories());
		for(int i = 0; i < cat.get(); ++i){
			out.print("mult"+i);
			out.print(SEP);
			out.print("left"+i);
			out.print(SEP);
			out.print("right"+i);
			out.print(SEP);
		}
		out.println();
		final AtomicReference<PrintWriter> pw = new AtomicReference<PrintWriter>(out);
		cGraph.getGraph().processArcs(new TouchEach<Arc<ContigInfo, ReadWrapper>>() {

			@Override
			public void touch(Arc<ContigInfo, ReadWrapper> arc) {
				StringBuffer sb = new StringBuffer();
				for(int i = 0; i < cat.get(); ++i	){
					CategoryReadInfo info = arc.getValue().getInfo(i);
					if(null != info){
						Integer mult = info.getMultiplicity();
						sb.append(mult.toString());	
						sb.append(SEP+arc.getLeft().getValue().getLength() + SEP+arc.getRight().getValue().getLength());
//						if(mult > 40 && mult < 75){
//							System.out.println(arc + ": " + info);
//						}
					} else {
						sb.append("0\t0\t0");
					}
					sb.append(SEP);
				}
				pw.get().println(sb.toString());
			}
		});	
	}

	private String getStatsFilePrefix() {
		return getQueueName();
	}
	

}